package com.gzx.bi.xxljob;

import com.gzx.bi.modular.screen.service.GzxBICallRecordService;
import com.gzx.bi.modular.screen.util.ScreenDateUtils;
import com.gzx.bi.modular.screen.vo.GzxLocalDateTimeVo;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import vip.xiaonuo.common.tenant.TenantContext;

import java.util.function.Consumer;

/**
 * @author xbl
 * &#064;description  报表定时任务
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class StatisticBIXxlJob {

    private final GzxBICallRecordService biService;

    //跑当月，只执行一次
    @XxlJob("scheduleBIMonth")
    public void scheduleBIMonth() {
        executeCommonJob("本月统计", biService::scheduleBIMonth);
    }

    //本月通话统计
    @XxlJob("scheduleBIMonthCallJobHandler")
    public void scheduleBIMonthCall() {
        executeCommonJob("本月通话统计", biService::scheduleBIMonthCall);
    }

    //团队坐席统计
    @XxlJob("scheduleBITeamAgentJobHandler")
    public void scheduleBITeamAgent() {
        executeCommonJob("团队坐席统计", biService::scheduleBITeamAgent);
    }

    //通话趋势分析
    @XxlJob("scheduleBICallTrendJobHandler")
    public void scheduleBICallTrend() {
        executeCommonJob("通话趋势分析", biService::scheduleBICallTrend);
    }

    //坐席状态统计
    @XxlJob("scheduleBIAgentStatusJobHandler")
    public void scheduleBIAgentStatus() {
        executeCommonJob("坐席状态统计", biService::scheduleBIAgentStatus);
    }

    //今日通话分析
    @XxlJob("scheduleBITodayCallJobHandler")
    public void scheduleBITodayCall() {
        executeCommonJob("今日通话分析", biService::scheduleBITodayCall);
    }

    //历史接通分析
    @XxlJob("scheduleBIHistoryAnswerJobHandler")
    public void scheduleBIHistoryAnswer() {
        executeCommonJob("历史接通分析", biService::scheduleBIHistoryAnswer);
    }

    //主报表
    @XxlJob("scheduleBIMainJobHandler")
    public void scheduleBIMain() {
        //编译器会自动推断这是一个 Consumer<String> 实例，因为 scheduleBIMain 方法的参数和返回值与 Consumer 接口的抽象方法 void accept(T t) 匹配。
        //Consumer<String> 是函数式接口，其唯一抽象方法为 void accept(String s)。只要方法签名（参数类型 + 返回类型）匹配，方法引用或 Lambda 表达式就可以赋值给该接口。
        //task.accept(currentDate) 实际上调用了 biService 中对应的方法，间接执行了scheduleBIMain具体的业务逻辑。
        executeCommonJob("主报表", biService::scheduleBIMain);
    }

    /**
     * 统一执行任务逻辑
     *
     * @param jobName 任务名称（用于日志）
     * @param task    业务逻辑（BiConsumer 或 Function）
     */
    private void executeCommonJob(String jobName, Consumer<GzxLocalDateTimeVo> task) {
        log.info("[START] job={}", jobName);
        long startTime = System.currentTimeMillis();
        long threadId = Thread.currentThread().threadId(); // 统一获取线程ID
        try {
            // 统一处理租户过滤
            log.info("禁用租户过滤 [线程ID: {}]", threadId);
            TenantContext.disableTenantFilter();
            GzxLocalDateTimeVo date = ScreenDateUtils.getNowDate();
            task.accept(date);
        } catch (Exception e) {
            log.error("[FAILED] job={}, cost={}ms", jobName, System.currentTimeMillis() - startTime, e);
            throw e; // 抛出异常让XXL-Job捕获重试
        } finally {
            log.info("启用租户过滤 [线程ID: {}]", threadId);
            TenantContext.enableTenantFilter();
            TenantContext.clear();
            log.info("{} 统计任务执行时间: {} 毫秒", jobName, System.currentTimeMillis() - startTime);
        }
    }
}
